package utils

import (
	"bufio"
	"fmt"
	"image"

	// "image/draw"
	"image/color"
	"image/png"
	_ "image/png"
	"os"
	"strings"

	"golang.org/x/image/draw"
)

func Run() {
	// t1 := time.Now().Unix()
	// for i := 0; i < 100; i++ {
	// s1 := "aa"
	// s2 := "bb"
	// var bd strings.Builder
	// for j := 0; j < 50000000; j++ {
	// 	bd.WriteString(s1)
	// 	bd.WriteString(s2)
	// }
	// s := bd.String()
	// ss(s)

	// 拼接过程产生新的字符串，s + s1 + s2在赋值给s之前就存在于一片地址中
	// 推荐的方法就是一直往一个内存的切片里推，没有新内存产生！
	// s := ""
	// for j := 0; j < 5; j++ {
	// 	s = s + s1 + s2
	// 	fmt.Println(&s)
	// }
	// ss(s)

	// 随便写一种,在这种设定下只要不是猛开内存，都挺快的，[]byte转为string这个内置设定也挺管用
	// sArr := []byte{}
	// for j := 0; j < 50000000; j++ {
	// 	sArr = append(sArr, s1...)
	// 	sArr = append(sArr, s2...)
	// }
	// s := string(sArr)
	// ss(s)
	// }
	// fmt.Println(time.Now().Unix() - t1)
	// var bd strings.Builder
	// bd.WriteString("aa")
	// bd.WriteString("bb")
	// str := bd.String()
	// fmt.Println(str, reflect.TypeOf(str))
	// bd.Reset()

	// bd.WriteString("cc")
	// fmt.Println(bd.String())

	// s := "sdsd556a你"
	// sArr := []byte{}
	// sArr = append(sArr, s...)
	// fmt.Println(sArr, string(sArr))
	readPic()
}

func readPic() image.Image {
	f, err := os.Open("C://Users//王春雨//Desktop//project//gomvc//public//image//point.png")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	img, fmtName, err := image.Decode(f)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Name: %v, Bounds: %+v, Color: %+v", fmtName, img.Bounds(), img.ColorModel())
	// img = image.NewRGBA(image.Rect(0, 0, 300, 300))
	jpg := image.NewRGBA(img.Bounds())
	// draw.Draw第一个参数接受draw.Image，draw.Image比image.Image接口多了Set方法，*image.Gray接受了set，所以符合draw.Image接口
	draw.Draw(jpg, img.Bounds(), img, img.Bounds().Min, 1)
	sub := jpg.SubImage(image.Rect(0, 0, jpg.Bounds().Dx(), jpg.Bounds().Dy()/2))
	// sub := jpg.SubImage(image.Rectangle{
	// 	Min: image.Point{
	// 		X: 0,
	// 		Y: 0,
	// 	},
	// 	Max: image.Point{
	// 		X: 700,
	// 		Y: 700,
	// 	},
	// })
	sub = resizePic(jpg, 1600, 800, true, 1, true)
	savePic(sub)
	return img
}
func savePic(img image.Image) {

	f, err := os.Create("C://Users//王春雨//Desktop//project//gomvc//public//image//point_out.png")
	if err != nil {
		panic(err)
	}
	defer f.Close()
	b := bufio.NewWriter(f)
	// fmt.Println(reflect.TypeOf(img))
	err = png.Encode(b, img)
	if err != nil {
		panic(err)
	}
	b.Flush()
}

func calcResizedRect(width int, src image.Rectangle, height int, centerAlign bool) image.Rectangle {
	var dst image.Rectangle
	if width*src.Dy() < height*src.Dx() { // width/src.width < height/src.height
		ratio := float64(width) / float64(src.Dx())

		tH := int(float64(src.Dy()) * ratio)
		pad := 0
		if centerAlign {
			pad = (height - tH) / 2
		}
		dst = image.Rect(0, pad, width, pad+tH)
	} else {
		ratio := float64(height) / float64(src.Dy())
		tW := int(float64(src.Dx()) * ratio)
		pad := 0
		if centerAlign {
			pad = (width - tW) / 2
		}
		dst = image.Rect(pad, 0, pad+tW, height)
	}

	return dst
}

func resizePic(img image.Image, width int, height int, keepRatio bool, fill int, centerAlign bool) image.Image {
	outImg := image.NewRGBA(image.Rect(0, 0, width, height))
	if !keepRatio {
		draw.BiLinear.Scale(outImg, outImg.Bounds(), img, img.Bounds(), draw.Over, nil)
		return outImg
	}

	if fill != 0 {
		fillColor := color.RGBA{R: uint8(fill), G: uint8(fill), B: uint8(fill), A: 255}
		draw.Draw(outImg, outImg.Bounds(), &image.Uniform{C: fillColor}, image.Point{}, draw.Src)
	}
	dst := calcResizedRect(width, img.Bounds(), height, centerAlign)
	// 核心就这一行
	draw.ApproxBiLinear.Scale(outImg, dst.Bounds(), img, img.Bounds(), draw.Over, nil)
	return outImg
}

// func subImg() {
// 	pic := readPic()
// 	fmt.Printf("Type: %T\n", pic)
// 	img := jpg2RCBA(pic)

// 	sub := img.SubImage(image.Rect(0, 0, pic.Bounds().Dx(), pic.Bounds().Dy()/2))
// 	savePic(sub.(*image.RGBA))
// }

func joinStr(a, b string) string {
	var bd strings.Builder
	bd.WriteString(a)
	bd.WriteString(b)
	return bd.String()
}

type Base interface {
	Get(string) string
}

type SL struct {
}

func (*SL) Get(str string) string {
	return "sdsds"
}

func ss(a Base) {
	fmt.Println(a.Get("s"))
}

// 先序遍历和中序
type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

func buildTree(preorder []int, inorder []int) *TreeNode {
	return nil
}

//罗马数转整数，100%
func romanToInt(s string) int {
	var result int = 0
	str := strings.Split(s, "")
	romap := map[string]int{
		"I": 1,
		"V": 5,
		"X": 10,
		"L": 50,
		"C": 100,
		"D": 500,
		"M": 1000,
	}
	m1 := map[string]int{
		"IV": 4,
		"IX": 9,
		"XL": 40,
		"XC": 90,
		"CD": 400,
		"CM": 900,
	}
	if len(str) == 1 {
		return romap[s]
	}
	for idx := 0; idx < len(str); idx++ {
		if idx < len(str)-1 {
			if romap[str[idx]] < romap[str[idx+1]] {
				key := str[idx] + str[idx+1]
				result = result + m1[key]
				idx++
			} else {
				result = result + romap[str[idx]]
			}
		} else {
			result = result + romap[str[idx]]
		}
	}
	fmt.Println(result)
	return result
}

// 罗马数，90.09%
func intToRoman(num int) string {
	result := ""
	intArr := [7]int{1, 5, 10, 50, 100, 500, 1000}
	// intArr := [7]int{1000, 500, 100, 50, 10, 5, 1}

	romap := map[int]string{
		1:    "I",
		5:    "V",
		10:   "X",
		50:   "L",
		100:  "C",
		500:  "D",
		1000: "M",
	}

	for {
		if num == 0 {
			break
		}
		for idx, v := range intArr {
			if idx == 6 && num >= v {
				num = num - 1000
				result = result + "M"
				break
			}
			if num < v {
				fmt.Println("num:", num)
				var value int
				var str string
				if num >= 4 && num < 5 {
					value = 4
					str = "IV"
				} else if num >= 9 && num < 10 {
					value = 9
					str = "IX"
				} else if num >= 40 && num < 50 {
					value = 40
					str = "XL"
				} else if num >= 90 && num < 100 {
					value = 90
					str = "XC"
				} else if num >= 400 && num < 500 {
					value = 400
					str = "CD"
				} else if num >= 900 && num < 1000 {
					value = 900
					str = "CM"
				} else {
					value = intArr[idx-1]
					str = romap[intArr[idx-1]]
				}
				num = num - value
				result = result + str
				break
			}
		}
	}

	fmt.Println(result)
	return result
}
